﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;

namespace MattDotson.GlobalToolkit.Tests
{
    public class TestCurrencyConverter : ICurrencyConverter
    {
        List<CurrencyConversion> conversionData = PopulateConversionData();

        private static List<CurrencyConversion> PopulateConversionData()
        {
            var tempList = new List<CurrencyConversion>();
            tempList.Add(new CurrencyConversion { From = "USD", To = "EUR", AsOf = DateTimeOffset.Now, Factor = 0.756m });
            tempList.Add(new CurrencyConversion{ From = "CAD", To = "USD", AsOf = DateTimeOffset.Now.AddDays(-10.0), Factor = 1.1m });
            tempList.Add(new CurrencyConversion{ From = "CAD", To = "USD", AsOf = DateTimeOffset.Now, Factor = 1.13m });

            return tempList;
        }

        #region ICurrencyConverter Members

        public bool CanConvert(CurrencyInfo fromCurrency, CurrencyInfo toCurrency)
        {
            return conversionData.Any(x => (x.From == fromCurrency.IsoCurrencyCode && x.To == toCurrency.IsoCurrencyCode)
                || (x.From == toCurrency.IsoCurrencyCode && x.To == fromCurrency.IsoCurrencyCode));
        }

        public Currency Convert(Currency value, CurrencyInfo toCurrency)
        {
            return Convert(value, toCurrency, DateTimeOffset.Now);
        }

        public Currency Convert(Currency value, CurrencyInfo toCurrency, DateTimeOffset time)
        {
            decimal? conversionFactor = GetConversionFactor(value.CurrencyInfo.IsoCurrencyCode, toCurrency.IsoCurrencyCode, time);
            if (null == conversionFactor)
            {
                return value;
            }

            return new Currency(value.Value / conversionFactor.Value, toCurrency);
        }

        private decimal? GetConversionFactor(string from, string to, DateTimeOffset asOf)
        {
            var list = conversionData
                .Where(x => (x.From == from && x.To == to));

            list.Union(conversionData.Where(y => (y.From == to && y.To == from))
                .Select(z => new CurrencyConversion { From = z.To, To = z.From, AsOf = z.AsOf, Factor = 1m / z.Factor }));

            var conversion = list.OrderBy(x => x.AsOf).FirstOrDefault(x => asOf > x.AsOf);
            if (null != conversion)
            {

                Debug.Print("Using conversion factor: From {0}, To {1}, Factor {2}, AsOf {3}", conversion.From, conversion.To, conversion.Factor, conversion.AsOf);
                return conversion.Factor;
            }

            return null;
        }

        #endregion
    }

    public class CurrencyConversion
    {
        public string From {get; set;}
        public string To { get; set; }
        public decimal Factor { get; set; }
        public DateTimeOffset AsOf { get; set; }
    }
}
